test(lint-shellcheck): deterministic barrier for worker-cap concurrency proof - #542
Merged
Conversation
…a file barrier test_default_worker_cap used sleep 0.1 inside the ShellCheck stub to widen a race window for observing two-way concurrency, which QA rules forbid and which host load can silently weaken (max_active could observe 1 even when the real cap is 2, since the old assertion only required >= 1). Workers now register at a flock-serialized counter and all release together once exactly two are concurrently registered, making the max_active == 2 assertion a deterministic property of the protocol. A bounded 5s deadline fails the stub with a clear message instead of hanging if the cap ever degrades to 1. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0177ds9nxEMtsh3bwpBxNHYx
qa-tester's gate review correctly flagged that the bounded busy-wait (sleep-in-a-loop) still counted as forbidden sleep-based synchronization. Switch to a blocking read on a bidirectionally-opened FIFO (open O_RDWR never blocks, sidestepping the open()-hangs-forever failure mode a prior ticket hit with a read-only/write-only FIFO) with a bounded -t timeout as the only failure path, and reuse the repo's existing serialize_with_lock helper for the counter mutex instead of a bespoke flock call (critic's portability finding). Also fixed the fixture's total shell-file count, which was odd and left the last worker of the sliding window unpaired. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0177ds9nxEMtsh3bwpBxNHYx
…ner wakes qa-tester's second gate round found that the releasing worker wrote its release signal and immediately proceeded toward deregistration without confirming the released worker actually woke up -- under a hypothetical cap-3 regression, both original workers could deregister before a concurrently-forked third worker reached the counter lock, letting the observed max_active read 2 even though 3 were briefly resident. Add a second FIFO for a blocking ack: the releaser now waits for the released worker's ack before either side deregisters, closing that asymmetric fast-exit window. Verified with a jobs=3 mutation of the fixture's copy of lint-shellcheck.sh -- the test now observes max_active=6 and fails, where it previously would have reported 2 and passed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0177ds9nxEMtsh3bwpBxNHYx
screenleon
force-pushed
the
feat/cc552-worker-cap-barrier
branch
from
August 26, 2026 11:56
2e0ce06 to
c283ec6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
test_default_worker_capusedsleep 0.1inside the ShellCheck stub to widen a race window for observing two-way concurrency, which QA rules forbid and which host scheduling could silently weaken (the old assertion only requiredmax_active >= 1, so it would pass even without genuine overlap).serialize_with_lockand block on a blocking FIFO read (bounded 5s timeout, never a polling sleep) until a second worker signals release; a second FIFO carries an ack so the releasing worker doesn't exit before the released worker actually wakes, closing an asymmetric fast-exit window a gate reviewer found.max_active == 2(a real, deterministic proof of overlap) instead of>= 1. If the real cap ever collapses to 1, the lone worker's bounded FIFO read times out and fails with a clear message instead of hanging (avoiding the FIFO-open hang shape from CC-543).Test plan
bash tests/shell/test-lint-shellcheck.sh(17/17, including the changed case, run 5x for stability)tools/lint/lint-shellcheck.shclean on the whole repolint-shellcheck.sh: confirmed the barrier now observesmax_active=6and fails, where it previously would have silently reported 2 and passedpmctl gate run --executor codex --policy generic→ GO (after 2 remediation rounds: portable-lock reuse + sleep-free blocking wait, then the ack-handshake fix)tests/bin/run-all-tests.sh→ 104 passed, 0 failed, 0 skipped🤖 Generated with Claude Code
https://claude.ai/code/session_0177ds9nxEMtsh3bwpBxNHYx